% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
%
%            File:  test8b10b.m
%     Description:  Исследование влияния ошибок на передаваемые данные
%                   при использовании 8b10b кодирования
%       
%         Created:  07.03.2013 16:20:14
%          Author:  Aleksey Golovchenko (lexgolovchenko@gmail.com)
%    Organization:  St.Petersburg State Polytecnical Universisy
%
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %

%
% Тест 8b10b кода
% 
function [err_detect_cntr, berr_undetect, burst_berr] = test8b10b(iter_num, errnum, verbousout)
    
    if nargin < 2
        error(message('Not enought input arguments!'));    
    end
    
    % Для подробного отладочного вывода
    global debug;
    debug = verbousout;
           
    % Инициализация генератора случайных чисел
    rng('shuffle');
        
    % кодер и декодер для 8b10b кода
    ENC = enc8b10b;
    DEC = dec8b10b;
        
    % счетчик обнаруженных ошибок
    err_detect_cntr = 0;        
    
    % Необнаруженные ошибки будем распределять по числу
    % битов, которыми отличаются исходный байт от декодированного
    % и по длине пакета ошибок (расстояние меду крайними 1)
    berr_undetect = zeros(1,8);        
    burst_berr = zeros(1,8);
           
    for i = 1:iter_num
        
        in = randi([0,255]);

        enc_data = ENC.encode(0, 0, in);
        if debug ~= 0 
            fprintf(1, '%-20s 0x%2.2X \n', 'Input data', in);
            fprintf(1, '%-20s 0x%3.3X \n', 'Codeword', enc_data);
        end
        
        err = err_channel(errnum);
        enc_data = bitxor(enc_data, err);
        
        if debug ~= 0 
            fprintf(1, '%-20s 0x%3.3X \n', 'Codeword with error', enc_data);
        end

        [err_out, ctrl_out, out] = DEC.decode(enc_data);
                
        if err_out == 1            
            if debug ~= 0
                fprintf(1, 'Error detected! \n');
            end;            
            
            err_detect_cntr = err_detect_cntr + 1;                    
        elseif in ~= out       
            if debug ~= 0
                fprintf(1, '%-20s 0x%2.2X \n', 'Output data', out);
                fprintf(1, 'Undetect error! \n');            
            end
            
            % Разница межу входным и выходным байтами
            bytediff = bitxor(in, out);
            
            %
            % Определение числа битовых ошибок
            %            
            berr_count = 0;
            for j = 0:7
                if bitand(bitshift(1,j), bytediff) ~= 0
                    berr_count = berr_count + 1;
                end
            end
            berr_undetect(berr_count) = berr_undetect(berr_count) + 1;
            
            if debug ~= 0
                fprintf(1, 'Bit errors num = %d \n', berr_count); 
            end
            
            %
            % Определение длины "пакета ошибок"
            %            
            bg = 0;         % Позиция начала пакета ошибок
            ed = 0;         % Позиция конца пакета ошибок
            for j = 0:7
                if bitand(bitshift(1,j), bytediff) ~= 0        
                    bg = j + 1;
                    break;
                end
            end

            for j = 0:7
                if bitand(bitshift(1,7-j), bytediff) ~= 0
                    ed = (7 - j) + 1;
                    break;
                end
            end                                          
            burst_berr(ed-bg+1) = burst_berr(ed-bg+1) + 1;
            
            if debug ~= 0
                fprintf(1, 'Burst error length = %d \n', ed-bg+1); 
            end
            
        else
            if debug ~= 0
                fprintf(1, '%-20s 0x%2.2X \n', 'Output data', out);
                fprintf(1, 'Transmit OK! \n');            
            end    
        end
        
        if debug ~= 0
            fprintf(1, '\n\n'); 
        end
    end

end

% 
% Внесение ошибок в передаваемое кодовое слово
%
function err = err_channel(errnum)

    global debug;

    % Случайная единичная ошибка для кодового слова    
    err = 0;    
    errpos = randi([0,9],[errnum,1],'uint32');
    for i = 1:errnum    
        err = bitor(err, bitshift(1,errpos(i)));
    end
        
    if debug ~= 0
        fprintf(1, '%-20s 0x%3.3X\n', 'Error', err);
    end;        
end
